package org.jks.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.hibernate.exception.ConstraintViolationException;
import org.jks.config.Config;
import org.jks.constant.Constants;
import org.jks.constant.SysConfig;
import org.jks.excel.DeviceReMonthUtil;
import org.jks.excel.DeviceReUtil;
import org.jks.excel.DeviceUtil;
import org.jks.model.Device;
import org.jks.model.DeviceInOut;
import org.jks.model.DeviceRe;
import org.jks.model.DeviceRecipient;
import org.jks.model.DeviceStatus;
import org.jks.model.DeviceType;
import org.jks.model.Flight;
import org.jks.model.RecipientOrder;
import org.jks.model.User;
import org.jks.model.Work;
import org.jks.model.WorkDevice;
import org.jks.report.model.ReportDeviceRe;
import org.jks.request.model.Ids;
import org.jks.request.model.UIDevice;
import org.jks.request.model.UIDeviceOut;
import org.jks.request.model.UIDeviceRe;
import org.jks.response.model.ActionResult;
import org.jks.response.model.UITable;
import org.jks.service.DeviceInOutService;
import org.jks.service.DeviceReService;
import org.jks.service.DeviceRecipientService;
import org.jks.service.DeviceService;
import org.jks.service.DeviceStatusService;
import org.jks.service.DeviceTypeService;
import org.jks.service.FlightService;
import org.jks.service.UserService;
import org.jks.service.WorkDeviceService;
import org.jks.service.WorkService;
import org.jks.util.DateUtil;
import org.jks.util.FileUtil;
import org.jks.util.JsonUtil;
import org.jks.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/device")
public class DeviceController {
	@Autowired
	UserService userService;
	@Autowired
	WorkService workService;
	@Autowired
	WorkDeviceService workDeviceService;
	@Autowired
	DeviceService deviceService;
	@Autowired
	DeviceTypeService deviceTypeService;
	@Autowired
	DeviceStatusService deviceStatusService;
	@Autowired
	DeviceInOutService deviceInOutService;
	@Autowired
	FlightService flightService;
	@Autowired
	DeviceRecipientService deviceRecipientService;
	
	@Autowired
	DeviceReService deviceReSevice;
	
	@RequestMapping("/add")
	public void add(UIDevice uiDevice, HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		User user = (User) session.getAttribute(Constants.SESSION_ACCOUNT);
		ActionResult ar = new ActionResult();
		String imgPath = uiDevice.getImgPath();
		String targetPath = null;
		String randomName = null;
		ServletContext servletContext = request.getServletContext();
		String basePath = servletContext.getRealPath("/");
		
		if(imgPath != null){
			targetPath = SysConfig.ATTACHEMENT + File.separator + SysConfig.DEVICE_IMG;
			randomName = DateUtil.toString(new Date(), "yyyyMMddHHmmss") + "." + FileUtil.getExtension(imgPath);
			FileUtil.copyFile(servletContext, imgPath, targetPath, true, randomName);
		}
		
		try {
			Device device = new Device();
			if(imgPath != null){
				device.setImgPath(targetPath + File.separator + randomName);
			}
			else{
				device.setImgPath("");
			}
			device.setTdCode(uiDevice.getTdCode());
			device.setBrand(uiDevice.getBrand());
			device.setManufacturers(uiDevice.getManufacturers());
			device.setModel(uiDevice.getModel());
			device.setNo(uiDevice.getNo());
			device.setOperationTime(DateUtil.toDate(uiDevice
					.getOperationTime(), "yyyy-MM-dd"));
			DeviceType deviceType = deviceTypeService.findById(uiDevice.getDeviceTypeId());
			device.setType(deviceType);
			DeviceStatus deviceStatus = new DeviceStatus();
			deviceStatus.setId(uiDevice.getDeviceStatusId());
			device.setCurrentStatus(deviceStatus);
			device.setIsSparePart(uiDevice.isIsSparePart());
			Flight flight = flightService.findById(uiDevice.getFlightId());
			device.setFlight(flight);
			deviceService.save(device);
			
			DeviceInOut deviceInOut = new DeviceInOut();
			deviceInOut.setType(DeviceInOut.TYPE_IN);
			deviceInOut.setTdCode(device.getTdCode());
			deviceInOut.setNo(device.getNo());
			deviceInOut.setDeviceType(device.getType().getName());
			deviceInOut.setBrand(device.getBrand());
			deviceInOut.setManufacturers(device.getManufacturers());
			deviceInOut.setModel(device.getModel());
			
			deviceInOut.setOperator(user);
			deviceInOut.setTime(new Date());
			deviceInOutService.save(deviceInOut);
			ar.setSuccess(true);
			
		} 
		catch( ConstraintViolationException e){
			ar.setMsg("设备编号或二维码冲突");
		}
		catch (Exception e) {
			ar.setMsg("添加设备失败");
		}
		if(!ar.isSuccess()){
			/*删除文件*/
			FileUtil.delete(basePath + File.separator + targetPath + File.separator + randomName);
		}
		if(imgPath != null && !imgPath.endsWith("view/images/default_headpic.png")){
			FileUtil.delete(basePath + File.separator + imgPath);
		}
		ResponseUtil.returnJson(response, ar);
	}

	public void add(Device device, HttpServletRequest request,
			HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		try {
			deviceService.save(device);
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/deleteDeviceRe")
	public void deleteDeviceRe(Ids ids, HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		ActionResult ar = new ActionResult();
		try {
			deviceReSevice.delete(ids.getIds());
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg("删除失败");
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}

	@RequestMapping("/delete")
	public void delete(Ids ids, HttpServletRequest request,
			HttpServletResponse response, HttpSession session) {
		ActionResult ar = new ActionResult();
		ServletContext servletContext = request.getServletContext();
		String basePath = servletContext.getRealPath("/");
		try {
			for(long id : ids.getIds()){
				Device device = deviceService.findById(id);
				String imgPath = device.getImgPath();
				deviceService.delete(device);
				if(imgPath != null && !imgPath.endsWith("view/images/default_headpic.png")){
					FileUtil.delete(basePath + File.separator + imgPath);
				}
			}
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg("删除失败");
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}

	@RequestMapping("/delete/{id}")
	public void delete(@PathVariable long id, HttpServletRequest request,
			HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		try {
			deviceService.delete(id);
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/detail/{id}")
	public ModelAndView detail(@PathVariable long id, HttpSession session, Map<String, Object> model, HttpServletRequest request,
			HttpServletResponse response){
		try {
			Device device = deviceService.get( Device.class, id);
			List<DeviceRe> dRes = device.getDeviceRe();
			if(dRes != null && dRes.size() != 0)
			{
				for(DeviceRe d : dRes)
				{
					d.setDevice(null);
				}
			}
			model.put("device", JsonUtil.Object2Json(device));
		} catch (Exception e) {
			e.printStackTrace();
		}
		Config.init(request, response, session, model);
		return new ModelAndView("wuziMgr/device_detail", model);
	}

	@RequestMapping("/update")
	public void update(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String json = JsonUtil.getJson(request.getReader());
		UIDevice uiDevice= (UIDevice)JsonUtil.Json2Object(json, UIDevice.class);
		
		ActionResult ar = new ActionResult();
		Device device = deviceService.findById(uiDevice.getId());
		if(device == null){
			ar.setMsg("该设备已经被删除!");
			ResponseUtil.returnJson(response, ar);
			return;
		}
		String imgPath = uiDevice.getImgPath();
		if(device.getImgPath() == null)
		{
			device.setImgPath("view/images/default_headpic.png");
		}
		if(device.getImgPath() != null && imgPath != null){
			String  basePath = request.getServletContext().getRealPath("/");
			if(!device.getImgPath().equals(imgPath) && imgPath.endsWith("view/images/default_headpic.png")){
				FileUtil.delete(basePath + File.separator + device.getImgPath());
			}
			if(imgPath.contains(SysConfig.UPLOAD)){
				String  targetPath = SysConfig.ATTACHEMENT + File.separator + SysConfig.DEVICE_IMG;
				String randomName = DateUtil.toString(new Date(), "yyyyMMddHHmmss") + "." + FileUtil.getExtension(imgPath);
				FileUtil.moveFile(request.getServletContext(), imgPath, targetPath, true, randomName);
				device.setImgPath(targetPath + File.separator + randomName);
			}
		}
		
		try {
			List<DeviceRe> tempList = new ArrayList<DeviceRe>();
			if(uiDevice.getDeviceRe() != null && uiDevice.getDeviceRe().size() != 0)
			{
				for(UIDeviceRe r : uiDevice.getDeviceRe())
				{
					DeviceRe d = new DeviceRe();
					d.setCount(r.getCount());
					d.setDuration(r.getDuration());
					d.setExceptionInfo(r.getExceptionInfo());
					d.setFlightTime(DateUtil.toDate(r.getFlightTime(), "yyyy-MM-dd"));
					d.setId(r.getId());
					d.setInfo(r.getInfo());
					d.setMileage(r.getMileage());
					d.setType(r.getType());
					Device ddd = new Device();
					ddd.setId(uiDevice.getId());
					d.setDevice(ddd);
					tempList.add(d);
				}
				
				deviceReSevice.update(tempList);
			}
			
//			device.setDeviceRe(tempList);
			device.setTdCode(uiDevice.getTdCode());
			device.setId(uiDevice.getId());
			device.setBrand(uiDevice.getBrand());
			device.setManufacturers(uiDevice.getManufacturers());
			device.setModel(uiDevice.getModel());
			device.setNo(uiDevice.getNo());
			device.setOperationTime(DateUtil.toDate(uiDevice.getOperationTime(), "yyyy-MM-dd"));
			DeviceType deviceType = new DeviceType();
			deviceType.setId(uiDevice.getDeviceTypeId());
			device.setType(deviceType);
			DeviceStatus deviceStatus = new DeviceStatus();
			deviceStatus.setId(uiDevice.getDeviceStatusId());
			device.setCurrentStatus(deviceStatus);
			device.setIsSparePart(uiDevice.isIsSparePart());
			Flight flight = flightService.findById(uiDevice.getFlightId());
			device.setFlight(flight);
			deviceService.update(device);
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}

	public void update(Device device, HttpServletRequest request,
			HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		try {
			deviceService.save(device);
			ar.setSuccess(true);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}

	@RequestMapping("/all")
	public void all(HttpServletRequest request, HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		String[] limit = request.getParameterValues("limit");
		String[] pages = request.getParameterValues("page");
		int pagesize = 25;
		int page = 1;
		if(limit.length > 0){
			pagesize = Integer.valueOf(limit[0]);
		}
		if(pages.length > 0){
			page = Integer.valueOf(pages[0]);
		}
		try {
			long total = deviceService.count();
			List<Device> dss = deviceService.list(page, pagesize);
			if(dss != null && dss.size() != 0)
			{
				for(Device d : dss)
				{
					d.setDeviceRe(null);
				}
			}
			ar.setSuccess(true);
			UITable table = new UITable();
			table.setTotal(total);
			table.setRows(dss);
			ar.setData(table);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/list_flight")
	public void listFlight(HttpServletRequest request, HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		try {
			DeviceType deviceType = deviceTypeService.findByName(Constants.DEVICE_TYPE_FLIGHT);
			List<Device> dss = deviceService.listByType(deviceType.getId());
			ar.setSuccess(true);
			UITable table = new UITable();
			table.setRows(dss);
			ar.setData(table);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/listByType")
	public void listByType(long id, HttpServletRequest request, HttpServletResponse response){
		ActionResult ar = new ActionResult();
		try {
			List<Device> dss = null;
			DeviceStatus deviceStatus = deviceStatusService.findByName("备勤");
			if(id == -1){
				dss = deviceService.listAllByType(deviceStatus.getId());
			}
			else{
				dss = deviceService.listByType(id, deviceStatus.getId());
			}
			ar.setSuccess(true);
			UITable table = new UITable();
			table.setRows(dss);
			ar.setData(table);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/distinct")
	public void distinct(HttpServletRequest request, HttpServletResponse response) {
		ActionResult ar = new ActionResult();
		try {
			List<Device> dss = deviceService.distinct();
			ar.setSuccess(true);
			UITable table = new UITable();
			table.setRows(dss);
			ar.setData(table);
		} catch (Exception e) {
			ar.setMsg(e.getMessage());
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}

	@RequestMapping("/import")
	public void reverseSN(@RequestParam(value = "file") MultipartFile file,
			HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws IOException {
		ActionResult ar = new ActionResult();
		InputStream is = file.getInputStream();
		DeviceUtil.importExcel(session, deviceService, deviceTypeService,
				deviceStatusService, deviceInOutService, flightService, is, ar);

		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/upload_img")
	public void uploadImg(@RequestParam(value = "devimg") MultipartFile file,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		ActionResult ar = new ActionResult();
		ar.setSuccess(true);
		ar.setData(SysConfig.UPLOAD + File.separatorChar + file.getOriginalFilename());
		FileUtil.uploadFile(request.getServletContext(), file);
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/ck")
	public void outCk(UIDeviceOut uiDeviceOut, HttpServletRequest request, HttpServletResponse response, HttpSession session){
		ActionResult ar = new ActionResult();
		DeviceStatus ds = deviceStatusService.findByName("工作");
		User user = userService.findById(uiDeviceOut.getRecipientId());
		if(user == null){
			ar.setMsg("领用人没选择或者不存在");
			ResponseUtil.returnJson(response, ar);
			return;
		}
		Work work = workService.findById(uiDeviceOut.getWorkId());
		DeviceRecipient deviceRecipient = deviceRecipientService.findById(work.getDeviceRecipient().getId());
		List<RecipientOrder> temp = deviceRecipient.getRecipientOrders();
		long workNeedDeviceCount = 0;
		if(temp != null)
		{
			for(RecipientOrder r : temp)
			{
				workNeedDeviceCount += r.getCount();
			}
		}		
		
		List<Device> dss = new ArrayList<Device>();
		List<DeviceInOut> deviceInOuts = new ArrayList<DeviceInOut>();
		Date inTime = new Date();
		List<WorkDevice> workDevices = new ArrayList<WorkDevice>();
		for(long id : uiDeviceOut.getIds()){
			DeviceInOut deviceInOut = new DeviceInOut();
			Device device = deviceService.findById(id);
			device.setCurrentStatus(ds);
			deviceInOut.setTdCode(device.getTdCode());
			deviceInOut.setNo(device.getNo());
			deviceInOut.setDeviceType(device.getType().getName());
			deviceInOut.setManufacturers(device.getManufacturers());
			deviceInOut.setBrand(device.getBrand());
			deviceInOut.setModel(device.getModel());
			deviceInOut.setOperator(user);
			deviceInOut.setType(DeviceInOut.TYPE_OUT);
			deviceInOut.setTime(inTime);
			dss.add(device);
			deviceInOuts.add(deviceInOut);
			if(work != null){
				WorkDevice workDevice = new WorkDevice();
				workDevice.setDevice(device);
				workDevice.setWork(work);
				workDevices.add(workDevice);
				device.setWork(work);
				work.getDevices().add(device);
			}
		}
		try{
			long curOutCount = work.getOutCount() + dss.size();
			work.setOutCount(curOutCount);
			
			if(workNeedDeviceCount == curOutCount) //所有的设备出库则该任务为开始
			{
				work.setState(1);
			}
			workService.update(work);
			
			deviceService.update(dss);
			deviceInOutService.save(deviceInOuts);
			if(workDevices.size() > 0){
				workDeviceService.save(workDevices);
			}
			ar.setSuccess(true);
		}
		catch(Exception e){
			ar.setMsg("操作失败");
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/download")
	public void downloadTemplate(HttpServletRequest request, HttpServletResponse response, HttpSession session){
		String basePath = request.getServletContext().getRealPath("/");
		String filename = "设备导入模板.xlsx";
		String path = basePath + File.separator + "templates" + File.separator + "export_template" + File.separator + filename;
		FileUtil.download(path, filename, response);
	}
	
	@RequestMapping("/available")
	public void availCount(long id, HttpServletRequest request, HttpServletResponse response, HttpSession session){
		ActionResult ar = new ActionResult();
		try{
			DeviceType deviceType = deviceService.findById(id).getType();
			long count = 0;
			if(deviceType != null){
				count = deviceService.countByType(deviceType);
			}
			ar.setData(count);
			ar.setSuccess(true);
		}
		catch(Exception e){
			ar.setMsg("服务出现错误");
			e.printStackTrace();
		}
		ResponseUtil.returnJson(response, ar);
	}
	
	@RequestMapping("/exportDeviceRe/{id}")
	public void exportDeviceRe(@PathVariable long id, HttpServletRequest request, HttpServletResponse response)
	{
		try{
			Device device = deviceService.findById(id);
			List<DeviceRe> tempList = device.getDeviceRe();
			if(tempList != null && tempList.size() != 0)
			{
				List<ReportDeviceRe> res = new ArrayList<ReportDeviceRe>();
				for(DeviceRe r : tempList)
				{
					ReportDeviceRe reportRe = new ReportDeviceRe();
					reportRe.setCount(r.getCount() + "");
					reportRe.setDeviceName(device.getBrand()); //TODO
					reportRe.setDeviceNo(device.getNo());
					reportRe.setDuration(r.getDuration() + "");
					reportRe.setExceptionInfo(r.getExceptionInfo());
					reportRe.setFlightTime(DateUtil.toString(r.getFlightTime(), "yyyyMMdd"));
					reportRe.setInfo(r.getInfo());
					reportRe.setMileage(r.getMileage() + "");
					reportRe.setType(r.getType());
					
					res.add(reportRe);
				}
				DeviceReUtil.export(response, res);
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@RequestMapping("/exportDeviceReTj/{type}/{year}/{month}")
	public void exportDeviceReTj(@PathVariable long type,
			@PathVariable long year, @PathVariable long month,
			HttpServletRequest request, HttpServletResponse response) {
		List<DeviceRe> tempList = new ArrayList<DeviceRe>();
		if(type == 1)
		{
			tempList = deviceReSevice.search(year + "-01-01", year + "-12-31");
		}
		else
		{
			int days = getDays(year, Integer.valueOf(month+ ""));
			tempList = deviceReSevice.search(year + "-" + month + "-01", year + "-" + month + "-" + days);
			List<ReportDeviceRe> res = new ArrayList<ReportDeviceRe>();
			for(DeviceRe r : tempList)
			{
				Device device = r.getDevice();
				ReportDeviceRe reportRe = new ReportDeviceRe();
				reportRe.setCount(r.getCount() + "");
				reportRe.setDeviceName(device.getBrand());
				reportRe.setDeviceNo(device.getNo());
				reportRe.setDuration(r.getDuration() + "");
				reportRe.setExceptionInfo(r.getExceptionInfo());
				reportRe.setFlightTime(DateUtil.toString(r.getFlightTime(), "yyyyMMdd"));
				reportRe.setInfo(r.getInfo());
				reportRe.setMileage(r.getMileage() + "");
				reportRe.setType(r.getType());
				
				res.add(reportRe);
			}
			DeviceReMonthUtil.export(response, res, year + "年" + month + "月");
		}
	}
		
	private int getDays(long year, int month)
	{
		switch(month)
		{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			return 31;
		case 2:
			return isLeapYear(year) ? 29 : 28;
		case 4:
		case 6:
		case 9:
		case 11:
			return 30;
		default:
			return -1;
		}
	}
	
	private boolean isLeapYear(long year){
		if(year % 100 == 0)
		{
			if(year % 400 == 0)
			{
				return true;
			}
		}
		else if(year % 4 == 0)
		{
			return true;
		}
		return false;
	}
}
